package com.runjian.rundo.iot.agent.common.thread;

import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.slf4j.MDC;

import com.runjian.rundo.bmp.kernel.common.spring.context.utils.MdcUtils;
import com.runjian.rundo.iot.agent.common.config.ScheduledConfigurationProperties;
import com.runjian.rundo.iot.agent.common.consts.ConfigurationPropertiesConst;

import lombok.Getter;
import lombok.Setter;

/**
 * 任务定时执行工厂
 *
 * @author CaoQingHua
 */
@Setter
@Getter
public class ScheduledExecutorFactory {

    private final ScheduledConfigurationProperties scheduledConfigurationProperties;
    /**
     * 定时线程池
     */
    private ScheduledThreadPoolExecutor scheduledPool;

    public ScheduledExecutorFactory(ScheduledConfigurationProperties scheduledConfigurationProperties) {
        this.scheduledConfigurationProperties = scheduledConfigurationProperties;
        CommonThreadFactory threadFactory = new CommonThreadFactory(ConfigurationPropertiesConst.NETWORK_SCHEDULED_TASK_THREAD_NAME);
        this.scheduledPool = new ScheduledThreadPoolExecutor(scheduledConfigurationProperties.getScheduledTaskWorkerSize(), threadFactory);
        // 添加线程监控
        ThreadPoolMonitor.addThreadPoolMonitor(threadFactory.getThreadGroupName(), scheduledConfigurationProperties.getMonitorSeconds(),
            scheduledPool);
    }

    public ScheduledFuture addSchedule(Runnable command, long delay, TimeUnit unit) {
        return scheduledPool.schedule(() -> {
            command.run();
            MDC.clear();
        }, delay, unit);
    }

    /**
     * 添加定时任务
     *
     * @param command 执行的程序
     * @param initialDelay 初始延迟时间
     * @param period 定时间隔
     * @param unit 时间单位
     * @return 反馈程序
     */
    public ScheduledFuture addScheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
        return scheduledPool.scheduleAtFixedRate(() -> {
            MdcUtils.setTraceIdIfAbsent();
            command.run();
            MDC.clear();
        }, initialDelay, period, unit);
    }
}
